package com.maisuiit.game;

/**
 * 功能：坦克游戏的2.01
 * 1、画出我的坦克
 * 2、让我的坦克动起来
 * 3、让我的坦克按下空格(space)键发射子弹
 * 4、让我的坦克可以连发子弹(最多连发5颗子弹)
 * 5、打到敌人坦克，敌人坦克就消失
 * 6、加入坦克被击中爆炸的效果
 * 7、让敌人的坦克可以自由随机移动
 * 8、控制坦克在指定的MyPanel面板中移动，不可越界
 * 9、让敌人的坦克发射子弹
 * 10、当我的坦克被敌人子弹击中，我的坦克爆炸
 * 11、防止敌人坦克重叠运动
 * 12、可以分关--做一个开始的Panel，它是空的主要是提示关卡
 * 13、游戏可以暂停、继续--暂停时将子弹、坦克速度设为0，坦克方向不变
 * 14、可以记录玩家的成绩
 * 15、java如何操作声音文件
 */
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.util.*;
import javax.sound.sampled.*;
public class MyTank07 extends JFrame implements ActionListener{
    //定义组件
    MyPanel mp=null;
    //定义一个开始面板
    MyStartPanel msp=null;
    //做出菜单
    JMenuBar jmb=null;
    //开始游戏
    JMenu jm1=null;
    JMenuItem jmi1=null;
    //退出游戏
    JMenuItem jmi2=null;
    //存盘退出
    JMenuItem jmi3=null;
    //接上局
    JMenuItem jmi4=null;

    public static void main(String[] args) {
        MyTank07 mt=new MyTank07();
    }
    //构造函数
    public MyTank07(){
        //创建菜单及菜单选项
        jmb=new JMenuBar();
        jm1=new JMenu("游戏(G)");
        //设置快捷方式
        jm1.setMnemonic('G');
        jmi1=new JMenuItem("开始新游戏(N)");
        jmi1.setMnemonic('N');
        //对jmi1相应
        jmi1.addActionListener(this);
        jmi1.setActionCommand("newgame");

        jmi2=new JMenuItem("退出游戏(E)");
        jmi2.setMnemonic('E');
        jmi2.addActionListener(this);
        jmi2.setActionCommand("exit");

        jmi3=new JMenuItem("存盘退出(S)");
        jmi3.setMnemonic('S');
        jmi3.addActionListener(this);
        jmi3.setActionCommand("save");

        jmi4=new JMenuItem("继续游戏(C)");
        jmi4.setMnemonic('C');
        jmi4.addActionListener(this);
        jmi4.setActionCommand("congame");

        jm1.add(jmi1);
        jm1.add(jmi2);
        jm1.add(jmi3);
        jm1.add(jmi4);
        jmb.add(jm1);
        this.setJMenuBar(jmb);

        //构建组件
        msp=new MyStartPanel();
        Thread t=new Thread(msp);
        t.start();
        this.add(msp);


        //设置JFrame窗体
        this.setTitle("坦克大战");//JFrame标题
        this.setSize(600, 500);//JFrame窗体大小
        this.setLocationRelativeTo(null);//在屏幕中心显示
        this.setVisible(true);//显示
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//退出并关闭JFrame

    }

    public void actionPerformed(ActionEvent e) {
        //对用户不同的点击，做出不同的处理
        if(e.getActionCommand().equals("newgame")){
            //创建战场面板
            mp=new MyPanel("newgame");
            //启动mp线程
            Thread ta=new Thread(mp);
            ta.start();
            //先删除旧的开始面板
            this.remove(msp);
            //加入组件
            this.add(mp);
            //监听
            this.addKeyListener(mp);
            //显示，刷新JFrame
            this.setVisible(true);
        }else if(e.getActionCommand().equals("exit")){
            //用户点击了退出菜单
            //保存用户游戏记录数据
            Recorder.keepRecording();
            System.exit(0);
        }else if(e.getActionCommand().equals("save")){
            //用户点击保存菜单
            //保存击毁敌人的数量和敌人的坐标
            Recorder.setEts(mp.ets);
            Recorder.keepRecAndEnemyTank();
            System.exit(0);
        }else if(e.getActionCommand().equals("congame")){
            //继续上次游戏
            //创建战场面板
            mp=new MyPanel("congame");

            //启动mp线程
            Thread ta=new Thread(mp);
            ta.start();
            //先删除旧的开始面板
            this.remove(msp);
            //加入组件
            this.add(mp);
            //监听
            this.addKeyListener(mp);
            //显示，刷新JFrame
            this.setVisible(true);
        }

    }
}
//开始面板--起提示作用
class MyStartPanel extends JPanel implements Runnable{
    int times=0;
    public void paint(Graphics g){
        super.paint(g);
        g.setColor(Color.black);
        g.fillRect(0, 0, 400, 300);
        //提示信息
        if(times%2==0){
            g.setColor(Color.yellow);
            //开关信息的字体
            Font myFont=new Font("华文新魏", Font.BOLD, 30);
            g.setFont(myFont);
            g.drawString("Stage: 1", 150, 150);
        }
    }

    public void run() {
        while(true){
            //休眠
            try {
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            }

            times++;
            //重画
            this.repaint();
        }
    }
}

//我的面板Panel
class MyPanel extends JPanel implements KeyListener,Runnable{//MyPanel继承Jpanel面板，创建KeyListener键盘接口和Runnable线程接口
    //定义一个我的坦克
    Hero hero=null;
    //定义声音播放
    AePlayWave apw=null;

    //定义敌人的坦克组
    Vector<EnemyTank> ets=new Vector<EnemyTank>();
    Vector<Node> nodes=new Vector<Node>();

    //定义炸弹集合
    Vector<Bomb> bombs=new Vector<Bomb>();

    int enSize=3;//初始敌人坦克数量

    //定义爆炸图片
    Image image1=null;
    Image image2=null;
    Image image3=null;

    //构造函数
    public MyPanel(String flag){
        hero=new Hero(200, 270);//我的坦克初始位置
        //恢复游戏记录
        Recorder.getRecoring();
        if(flag.equals("newgame")){
            //播放开战声音
            apw=new AePlayWave("e:\\tankgame\\tankmusic.wav");
            apw.start();
            //初始化敌人的坦克
            for(int i=0;i<enSize;i++){
                //创建一辆敌人的坦克对象
                EnemyTank et=new EnemyTank((i+1)*50, 0);
                //初始敌人坦克颜色
                et.setColor(2);
                //初始敌人坦克的方向
                et.setDirect(1);

                //将MyPanel的敌人向量交给该敌人坦克
                et.setEts(ets);

                //启动敌人坦克进程
                Thread t=new Thread(et);
                t.start();

                //给敌人坦克添加一颗子弹
                Shot s=new Shot(et.x+10, et.y+30, 1);
                //把子弹加入给敌人
                et.ss.add(s);
                Thread t2=new Thread(s);
                t2.start();

                //加入敌人坦克
                ets.add(et);
            }
        }else if(flag.equals("congame")){
            nodes=new Recorder().getNodesAndEnNums();
            //初始化敌人的坦克
            for(int i=0;i<nodes.size();i++){
                Node node=nodes.get(i);
                //创建一辆敌人的坦克对象
                EnemyTank et=new EnemyTank(node.x, node.y);
                //初始敌人坦克颜色
                et.setColor(2);
                //初始敌人坦克的方向
                et.setDirect(node.direct);

                //将MyPanel的敌人向量交给该敌人坦克
                et.setEts(ets);

                //启动敌人坦克进程
                Thread t=new Thread(et);
                t.start();

                //给敌人坦克添加一颗子弹
                Shot s=new Shot(et.x+10, et.y+30, 1);
                //把子弹加入给敌人
                et.ss.add(s);
                Thread t2=new Thread(s);
                t2.start();

                //加入敌人坦克
                ets.add(et);
            }
        }

        //初始化爆炸图片
        try {
            image1=ImageIO.read(new File("bomb1.gif"));
            image2=ImageIO.read(new File("bomb2.gif"));
            image3=ImageIO.read(new File("bomb3.gif"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //画出提示信息
    public void showInfo(Graphics g){
        //画出提示信息坦克(该坦克不参与战斗，只是用于显示提示信息)
        this.drawTank(80, 330, g, 1, 0);
        g.setColor(Color.BLACK);
        g.setFont(new Font("宋体",Font.BOLD,20));
        g.drawString(Recorder.getEnNum()+"", 110, 350);//显示敌人坦克数量

        this.drawTank(140, 330, g, 0, 0);
        g.setColor(Color.BLACK);
        g.setFont(new Font("宋体",Font.BOLD,20));
        g.drawString(Recorder.getMyLife()+"", 170, 350);//显示我的坦克数量

        //画出玩家的总成绩
        g.setColor(Color.black);
        g.setFont(new Font("宋体",Font.BOLD,20));
        g.drawString("您的总成绩", 420, 30);

        this.drawTank(420, 60, g, 1, 0);
        g.setColor(Color.black);
        g.setFont(new Font("宋体",Font.BOLD,20));
        g.drawString(Recorder.getAllEnNum()+"", 460, 80);
    }

    //重写paint函数
    public void paint(Graphics g){
        super.paint(g);//调用父类paint方法

        //画出提示信息
        this.showInfo(g);

        //设置Panel底色
        g.setColor(Color.black);
        g.fillRect(0, 0, 400, 300);//fillRect(0,0,X?,Y?)中X?/Y?为活动区域

        //画出自己的坦克
        if(hero.isLive==true){
            this.drawTank(hero.getX(), hero.getY(), g, 0, this.hero.direct);
        }

        //从ss向量中取出每一颗子弹并画出
        for(int i=0;i<this.hero.ss.size();i++){
            Shot myShot=hero.ss.get(i);
            //画出一颗子弹，判断子弹是否为空
            if(myShot!=null&&myShot.isLive==true){
                g.draw3DRect(myShot.x, myShot.y, 1, 1, false);
            }
            //判断子弹是否死亡
            if(myShot.isLive==false){
                //从向量ss中删除该子弹
                hero.ss.remove(myShot);
            }
        }

        //画出炸弹
        for(int i=0;i<bombs.size();i++){
            //取出炸弹
            Bomb b=bombs.get(i);
            if(b.life>6){
                g.drawImage(image1, b.x, b.y, 30, 30, this);
            }else if(b.life>3){
                g.drawImage(image2, b.x, b.y, 30, 30, this);
            }else {
                g.drawImage(image3, b.x, b.y, 30, 30, this);
            }
            //让b的生命值减少
            b.lifeDown();
            //如果炸弹生命值为0，就把该炸弹从bombs向量中去掉
            if(b.life==0){
                bombs.remove(b);
            }
        }

        //画出敌人的坦克
        for(int i=0;i<ets.size();i++){
            EnemyTank et=ets.get(i);
            if(et.isLive){
                this.drawTank(et.getX(), et.getY() , g, 1, et.getDirect());
                //再画出敌人坦克的子弹
                for(int j=0;j<et.ss.size();j++){
                    //取出子弹
                    Shot enemyShot=et.ss.get(j);
                    if(enemyShot.isLive){
                        g.draw3DRect(enemyShot.x, enemyShot.y, 1, 1, false);
                    }else{
                        //如果敌人的坦克死亡了就从向量Vector中去掉
                        et.ss.remove(enemyShot);
                    }
                }
            }
        }

    }

    //判断我的子弹是否击中敌人的坦克
    public void hitEnemyTank(){
        //遍历Vector集合类
        for(int i=0;i<hero.ss.size();i++){
            //先取子弹
            Shot myShot=hero.ss.get(i);
            //判断子弹是否有效
            if(myShot.isLive){
                //取出每一个敌人坦克与子弹进行判断
                for(int j=0;j<ets.size();j++){
                    //取出坦克
                    EnemyTank et=ets.get(j);
                    //判断敌人坦克是否还活着
                    if(et.isLive){
                        if(this.hitTank(myShot, et)){
                            apw=new AePlayWave("e:\\tankgame\\tank_explosion.wav");
                            apw.start();
                            //调用reduceEnNum()减少敌人坦克统计数
                            Recorder.reduceEnNum();
                            //调用addEnNumRec()增加消灭敌人坦克统计数
                            Recorder.addEnNumRec();
                        }
                    }
                }
            }
        }
    }

    //判断敌人的子弹是否击中我的坦克
    public void hitMe(){
        //取出每一个敌人的坦克
        for(int i=0;i<this.ets.size();i++){
            //取出敌人的坦克
            EnemyTank et=ets.get(i);
            //取出每一颗敌人的子弹
            for(int j=0;j<et.ss.size();j++){
                //取出子弹
                Shot enemyShot=et.ss.get(j);

                if(hero.isLive){
                    if(this.hitTank(enemyShot, hero)){


                    }
                }
            }
        }
    }

    //写一个函数专门判断子弹是否击中敌人坦克
    public boolean hitTank(Shot s,Tank et){
        boolean b=false;
        //判断该敌人坦克的方向
        switch(et.direct){
            case 0://敌人坦克向上或向下
            case 1:
                if(s.x>et.x&&s.x<et.x+20&&s.y>et.y&&s.y<et.y+29){
                    //击中方向为上或下的敌人坦克
                    //子弹死亡
                    s.isLive=false;
                    //敌人坦克死亡
                    et.isLive=false;
                    b=true;
                    //创建一颗炸弹
                    Bomb bomb=new Bomb(et.x, et.y);
                    //放入Vector向量中管理
                    bombs.add(bomb);
                }
                break;
            case 2://敌人坦克向左或向右
            case 3:
                if(s.x>et.x&&s.x<et.x+29&&s.y>et.y&&s.y<et.y+20){
                    //击中方向为左或右的敌人坦克
                    //子弹死亡
                    s.isLive=false;
                    //敌人坦克死亡
                    et.isLive=false;
                    b=true;
                    //创建一颗炸弹
                    Bomb bomb=new Bomb(et.x, et.y);
                    //放入Vector向量中管理
                    bombs.add(bomb);
                }
                break;
        }
        return b;
    }

    //画出坦克的函数
    public void drawTank(int x,int y,Graphics g,int type,int direct){
        //判断是什么类型的坦克
        switch(type){
            case 0:
                g.setColor(Color.cyan);//我的坦克颜色
                break;
            case 1:
                g.setColor(Color.yellow);//敌人坦克颜色
                break;
            case 2:
                g.setColor(Color.red);
                break;
        }

        //判断坦克的方向
        switch(direct){
            //向上走的坦克
            case 0:
                //画出我的坦克(到时再封装成一个函数)
                //1、画出左边的矩形
                g.fill3DRect(x, y, 5, 30, false);
                //2、画出右边的矩形
                g.fill3DRect(x+15, y, 5, 30, false);
                //3、画出中间矩形
                g.fill3DRect(x+5, y+5, 10, 20, false);
                //4、画出中间圆形
                g.fillOval(x+5, y+10, 10, 10);
                //5、画出线(炮筒)
                g.drawLine(x+10, y+15, x+10, y);
                break;
            //向下走的坦克
            case 1:
                g.fill3DRect(x, y, 5, 30, false);
                g.fill3DRect(x+15, y, 5, 30, false);
                g.fill3DRect(x+5, y+5, 10, 20, false);
                g.fillOval(x+5, y+10, 10, 10);
                g.drawLine(x+10, y+15, x+10, y+29);
                break;
            //向左走的坦克
            case 2:
                g.fill3DRect(x, y, 30, 5, false);
                g.fill3DRect(x, y+15, 30, 5, false);
                g.fill3DRect(x+5, y+5, 20, 10, false);
                g.fillOval(x+10, y+5, 10, 10);
                g.drawLine(x+15, y+10, x, y+10);
                break;
            //向右走的坦克
            case 3:
                g.fill3DRect(x, y, 30, 5, false);
                g.fill3DRect(x, y+15, 30, 5, false);
                g.fill3DRect(x+5, y+5, 20, 10, false);
                g.fillOval(x+10, y+5, 10, 10);
                g.drawLine(x+15, y+10, x+29, y+10);
                break;
        }
    }

    public void keyPressed(KeyEvent e) {//按下键事件a向左s向下d向右w向上
        if(e.getKeyCode()==KeyEvent.VK_W||e.getKeyCode()==KeyEvent.VK_UP){
            //向上
            this.hero.setDirect(0);
            this.hero.moveUp();
        }else if(e.getKeyCode()==KeyEvent.VK_S||e.getKeyCode()==KeyEvent.VK_DOWN){
            //设置我的坦克的方向,向下
            this.hero.setDirect(1);
            this.hero.moveDown();
        }else if(e.getKeyCode()==KeyEvent.VK_A||e.getKeyCode()==KeyEvent.VK_LEFT){
            //向左
            this.hero.setDirect(2);
            this.hero.moveLeft();
        }else if(e.getKeyCode()==KeyEvent.VK_D||e.getKeyCode()==KeyEvent.VK_RIGHT){
            //向右
            this.hero.setDirect(3);
            this.hero.moveRight();
        }

        //判断玩家是否按下空格键,不可接上面else if。不然不能同时按方向键和空格(space)键
        if(e.getKeyCode()==KeyEvent.VK_SPACE){
            apw=new AePlayWave("e:\\tankgame\\tank_Shelling_sound.wav");
            apw.start();
            //控制子弹连发
            if(this.hero.ss.size()<=4){
                //按下空格后开火
                this.hero.shotEnemy();
            }
        }

        //调用repaint()函数，来重绘界面
        this.repaint();
    }

    public void keyReleased(KeyEvent e) {//弹起键事件

    }

    public void keyTyped(KeyEvent e) {//按键输出值

    }

    //重写run函数
    public void run() {
        while(true){
            try {
                Thread.sleep(100);//休息100毫秒后重绘MyPanel面板
            } catch (Exception e) {
                e.printStackTrace();
            }

            this.hitEnemyTank();
            //判断敌人的子弹是否击中我的坦克
            this.hitMe();

            //重绘MyPanel面板
            this.repaint();
        }
    }
}

//播放声音的类
class AePlayWave extends Thread {
    private String filename;
    public AePlayWave(String wavfile) {
        filename = wavfile;

    }

    public void run() {
        File soundFile = new File(filename);
        AudioInputStream audioInputStream = null;
        try {
            audioInputStream = AudioSystem.getAudioInputStream(soundFile);
        } catch (Exception e1) {
            e1.printStackTrace();
            return;
        }

        AudioFormat format = audioInputStream.getFormat();
        SourceDataLine auline = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

        try {
            auline = (SourceDataLine) AudioSystem.getLine(info);
            auline.open(format);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        auline.start();
        int nBytesRead = 0;
        //这是缓冲
        byte[] abData = new byte[2048];

        try {
            while (nBytesRead != -1) {
                nBytesRead = audioInputStream.read(abData, 0, abData.length);
                if (nBytesRead >= 0)
                    auline.write(abData, 0, nBytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return;
        } finally {
            auline.drain();
            auline.close();
        }

    }
}

//记录恢复点
class Node{
    int x,y,direct;
    public Node(int x,int y,int direct){
        this.x=x;
        this.y=y;
        this.direct=direct;
    }
}

//记录类，同时也可以保存玩家的设置
class Recorder{
    //记录每关有多少敌人
    private static int enNum=20;
    //设置我有多少可用的人
    private static int myLife=3;
    //记录总共消灭了多少敌人的坦克
    private static int allEnNum=0;
    //从文件中恢复记录点
    private static Vector<Node> nodes=new Vector<Node>();

    private static FileWriter fw=null;
    private static BufferedWriter bw=null;
    private static FileReader fr=null;
    private static BufferedReader br=null;
    private static Vector<EnemyTank> ets=new Vector<EnemyTank>();

    //完成读取任务点任务
    public static Vector<Node> getNodesAndEnNums(){
        try {
            fr=new FileReader("e:\\tankgame\\tanksave.txt");
            br=new BufferedReader(fr);
            String n="";
            //先读一行
            n=br.readLine();
            allEnNum=Integer.parseInt(n);
            while((n=br.readLine())!=null){
                String []Recovery=n.split(" ");//split方法可以按一行字符中有多少个空间来返回数组
                Node node=new Node(Integer.parseInt(Recovery[0]),Integer.parseInt(Recovery[1]),Integer.parseInt(Recovery[2]));
                nodes.add(node);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                br.close();
                fr.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return nodes;
    }

    //保存击毁敌人的数量和敌人坦克坐标、方向
    public static void keepRecAndEnemyTank(){
        try {
            //创建
            fw=new FileWriter("e:\\tankgame\\tanksave.txt");
            bw=new BufferedWriter(fw);
            bw.write(allEnNum+"\r\n");

            //保存当前还活着的敌人坦克坐标、方向
            for(int i=0;i<ets.size();i++){
                //取出第一个坦克
                EnemyTank et=ets.get(i);
                if(et.isLive){
                    //活的保存
                    String recode=et.x+" "+et.y+" "+et.direct;//得到坐标x,y和方向direct
                    //写入到文件
                    bw.write(recode+"\r\n");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //关闭流,先开后关，后开先关
            try {
                bw.close();
                fw.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    //从文件中读取记录
    public static void getRecoring(){
        try {
            fr=new FileReader("e:\\tankgame\\tanksave.txt");
            br=new BufferedReader(fr);
            String n=br.readLine();
            allEnNum=Integer.parseInt(n);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                br.close();
                fr.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
    //把玩家击毁敌人坦克数量保存到文件中
    public static void keepRecording(){
        try {
            //创建
            fw=new FileWriter("e:\\tankgame\\tanksave.txt");
            bw=new BufferedWriter(fw);
            bw.write(allEnNum+"\r\n");
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //关闭流,先开后关，后开先关
            try {
                bw.close();
                fw.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    public static int getAllEnNum() {
        return allEnNum;
    }
    public static void setAllEnNum(int allEnNum) {
        Recorder.allEnNum = allEnNum;
    }
    public static int getEnNum() {
        return enNum;
    }
    public static void setEnNum(int enNum) {
        Recorder.enNum = enNum;
    }
    public static int getMyLife() {
        return myLife;
    }
    public static void setMyLife(int myLife) {
        Recorder.myLife = myLife;
    }

    public static Vector<EnemyTank> getEts() {
        return ets;
    }

    public static void setEts(Vector<EnemyTank> ets) {
        Recorder.ets = ets;
    }


    //敌人坦克死亡就减少坦克数
    public static void reduceEnNum(){
        enNum--;
    }
    //当消灭敌人的时候
    public static void addEnNumRec(){
        allEnNum++;
    }

}

//炸弹类
class Bomb{
    //定义炸弹的坐标
    int x,y;
    int life=9;//炸弹的生命
    boolean isLive=true;
    public Bomb(int x,int y){
        this.x=x;
        this.y=y;
    }
    //减少炸弹生命值
    public void lifeDown(){
        if(life>0){
            life--;
        }else{
            this.isLive=false;
        }
    }

}

//子弹类
class Shot implements Runnable{
    int x,y,direct,speed=3;//初始子弹x,y坐标,direct子弹方向,speed子弹速度

    //子弹是否还活着
    boolean isLive=true;//默认为活着

    public Shot(int x,int y,int direct){
        this.x=x;
        this.y=y;
        this.direct=direct;
    }

    public void run(){
        while(true){
            try {
                Thread.sleep(50);//让子弹休息50毫秒，防止快速消费内存
            } catch (Exception e) {
                e.printStackTrace();
            }

            switch(direct){
                case 0://向上
                    y-=speed;
                    break;
                case 1://向下
                    y+=speed;
                    break;
                case 2://向 左
                    x-=speed;
                    break;
                case 3://向右
                    x+=speed;
                    break;
            }
            //子弹何时死亡
            //判断该子弹是否碰到MyPanel面板的边缘
            if(x<0||x>400||y<0||y>300){
                this.isLive=false;
                break;
            }
        }
    }
}

//定义坦克类
class Tank{
    //表示坦克的X横坐标Y纵坐标
    int x=0,y=0;
    //direct坦克方向,0向上、1向下、2向左、3向右
    int direct=0;
    //坦克的速度
    int speed=1;
    //坦克颜色
    int color;

    boolean isLive=true;

    public Tank(int x,int y){
        this.x=x;
        this.y=y;
    }

    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    public int getDirect() {
        return direct;
    }
    public void setDirect(int direct) {
        this.direct = direct;
    }
    public int getSpeed() {
        return speed;
    }
    public void setSpeed(int speed) {
        this.speed = speed;
    }
    public int getColor() {
        return color;
    }
    public void setColor(int color) {
        this.color = color;
    }

}

//敌人坦克,把敌人坦克做成线程类
class EnemyTank extends Tank implements Runnable{
    int move=30;//敌人坦克移动步长(区域)
    int times=0;

    //定义一个向量，可以访问到MyPanel上所有敌人坦克
    Vector<EnemyTank> ets=new Vector<EnemyTank>();

    //定义一个向量，可以存放敌人的子弹
    Vector<Shot> ss=new Vector<Shot>();
    //敌人添加子弹，应在创建坦克和敌人的坦克子弹死亡后

    public EnemyTank(int x,int y){
        super(x,y);
    }

    //得到MyPanel的敌人坦克向量
    public void setEts(Vector<EnemyTank> tank){
        this.ets=tank;
    }

    //判断敌人坦克是否重叠
    public boolean isTouchOtherEnemy(){
        boolean b=false;

        switch(this.direct){
            case 0://敌人当前坦克向上
                //取出所有敌人坦克
                for(int i=0;i<ets.size();i++){
                    //取出第一个坦克
                    EnemyTank et=ets.get(i);
                    //如果不是当前的坦克
                    if(et!=this){
                        //如果敌人同伴的坦克向上或向下
                        if(et.direct==0||et.direct==1){
                            //判断敌人当前坦克左轮与同伴坦克(向上或向下)的位置比较
                            if(this.x>=et.x&&this.x<=et.x+20&&this.y>=et.y&&this.y<=et.y+30){
                                return true;
                            }
                            if(this.x+20>=et.x&&this.x+20<=et.x+20&&this.y>=et.y&&this.y<=et.y+30){
                                return true;
                            }
                        }
                        //如果敌人同伴的坦克向左或向右
                        if(et.direct==2||et.direct==3){
                            //判断敌人当前坦克右轮与同伴坦克(向左或向右)的位置比较
                            if(this.x>=et.x&&this.x<=et.x+30&&this.y>=et.y&&this.y<=et.y+20){
                                return true;
                            }
                            if(this.x+20>=et.x&&this.x+20<=et.x+30&&this.y>=et.y&&this.y<=et.y+20){
                                return true;
                            }
                        }
                    }
                }
                break;
            case 1://敌人当前坦克向下
                for(int i=0;i<ets.size();i++){
                    EnemyTank et=ets.get(i);
                    if(et!=this){
                        if(et.direct==0||et.direct==1){
                            if(this.x>=et.x&&this.x<=et.x+20&&this.y+30>=et.y&&this.y+30<=et.y+30){
                                return true;
                            }
                            if(this.x+20>=et.x&&this.x+20<=et.x+20&&this.y+30>=et.y&&this.y+30<=et.y+30){
                                return true;
                            }
                        }
                        if(et.direct==2||et.direct==3){
                            if(this.x>=et.x&&this.x<=et.x+30&&this.y+30>=et.y&&this.y+30<=et.y+20){
                                return true;
                            }
                            if(this.x+20>=et.x&&this.x+20<=et.x+30&&this.y+30>=et.y&&this.y+30<=et.y+20){
                                return true;
                            }
                        }
                    }
                }
                break;
            case 2://敌人当前坦克向左
                for(int i=0;i<ets.size();i++){
                    EnemyTank et=ets.get(i);
                    if(et!=this){
                        if(et.direct==0||et.direct==1){
                            if(this.x>=et.x&&this.x<=et.x+20&&this.y>=et.y&&this.y<=et.y+30){
                                return true;
                            }
                            if(this.x>=et.x&&this.x<=et.x+20&&this.y+20>=et.y&&this.y+20<=et.y+30){
                                return true;
                            }
                        }
                        if(et.direct==2||et.direct==3){
                            if(this.x>=et.x&&this.x<=et.x+30&&this.y>=et.y&&this.y<=et.y+20){
                                return true;
                            }
                            if(this.x>=et.x&&this.x<=et.x+30&&this.y+20>=et.y&&this.y+20<=et.y+20){
                                return true;
                            }
                        }
                    }
                }
                break;
            case 3://敌人当前坦克向右
                for(int i=0;i<ets.size();i++){
                    EnemyTank et=ets.get(i);
                    if(et!=this){
                        if(et.direct==0||et.direct==1){
                            if(this.x+30>=et.x&&this.x+30<=et.x+20&&this.y>=et.y&&this.y<=et.y+30){
                                return true;
                            }
                            if(this.x+30>=et.x&&this.x+30<=et.x+20&&this.y+20>=et.y&&this.y+20<=et.y+30){
                                return true;
                            }
                        }
                        if(et.direct==2||et.direct==3){
                            if(this.x+30>=et.x&&this.x+30<=et.x+30&&this.y>=et.y&&this.y<=et.y+20){
                                return true;
                            }
                            if(this.x+30>=et.x&&this.x+30<=et.x+30&&this.y+20>=et.y&&this.y+20<=et.y+20){
                                return true;
                            }
                        }
                    }
                }
                break;
        }

        return b;
    }

    //重写run()函数
    public void run() {

        while(true){
            switch(this.direct){
                case 0://坦克正在向上移动
                    for(int i=0;i<move;i++){
                        if(y>0&&!this.isTouchOtherEnemy()){//判断敌人坦克向上走不会越界
                            y-=speed;
                        }
                        try {
                            Thread.sleep(50);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 1://向下移动
                    for(int i=0;i<move;i++){
                        if(y<400&&!this.isTouchOtherEnemy()){//判断敌人坦克向下走不会越界
                            y+=speed;
                        }
                        try {
                            Thread.sleep(50);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 2://向左移动
                    for(int i=0;i<move;i++){
                        if(x>0&&!this.isTouchOtherEnemy()){//判断敌人坦克向左走不会越界
                            x-=speed;
                        }
                        try {
                            Thread.sleep(50);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 3://向右移动
                    for(int i=0;i<move;i++){
                        if(x<300&&!this.isTouchOtherEnemy()){//判断敌人坦克向右走不会越界
                            x+=speed;
                        }
                        try {
                            Thread.sleep(50);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    break;
            }

            this.times++;
            if(times%2==0){
                if(isLive){
                    if(ss.size()<5){
                        Shot s=null;
                        //没有子弹,添加子弹
                        switch(direct){
                            case 0:
                                s=new Shot(x+10, y, 0);
                                ss.add(s);
                                break;
                            case 1:
                                s=new Shot(x+10, y+29, 1);
                                ss.add(s);
                                break;
                            case 2:
                                s=new Shot(x, y+10, 2);
                                ss.add(s);
                                break;
                            case 3:
                                s=new Shot(x+29, y+10, 3);
                                ss.add(s);
                                break;
                        }
                        //启动敌人子弹线程
                        Thread t=new Thread(s);
                        t.start();
                    }
                }
            }

            //让坦克随机产生一个新的行驶方向
            this.direct=(int)(Math.random()*4);

            //判断敌人坦克是否已死亡
            if(this.isLive==false){
                //让坦克死亡后退出线程
                break;
            }
        }
    }
}

//我的坦克
class Hero extends Tank{
    //子弹
    //Shot s=null;
    Vector<Shot> ss=new Vector<Shot>();//Vector线程安全的集合类
    Shot s=null;

    public Hero(int x,int y){
        super(x,y);

    }

    //坦克开火
    public void shotEnemy(){

        switch(this.direct){//判断坦克方向来对应子弹运行方向
            case 0://向上
                //创建一颗子弹
                s=new Shot(x+10, y, 0);
                //将子弹加入到向量集中
                ss.add(s);
                break;
            case 1://向下
                s=new Shot(x+10, y+29, 1);
                ss.add(s);
                break;
            case 2://向左
                s=new Shot(x, y+10, 2);
                ss.add(s);
                break;
            case 3://向右
                s=new Shot(x+29, y+10, 3);
                ss.add(s);
                break;
        }
        //启动子弹线程
        Thread t=new Thread(s);
        t.start();
    }

    //坦克向上移动
    public void moveUp(){
        y-=speed;
    }
    //坦克向右移动
    public void moveRight(){
        x+=speed;
    }
    //坦克向下移动
    public void moveDown(){
        y+=speed;
    }
    //坦克向左移动
    public void moveLeft(){
        x-=speed;
    }
}